package com.junjie.checkin.security.service.impl;

import com.junjie.checkin.entity.TUser;
import com.junjie.checkin.mapper.UserMapper;
import com.junjie.checkin.response.auth.TokenResponse;
import com.junjie.checkin.security.service.AuthDetails;
import com.junjie.checkin.security.service.JwtService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author 洪浚杰
 * @description jwt服务实现类
 * @date 2025/6/9 14:17
 */
@Service
public class JwtServiceImpl implements JwtService<TokenResponse,AuthDetails> {
    private final String secret = "984677ad-2f83-4f92-bf61-854141729d25";  // 密钥
    private final Integer expired = 120;
    private final Integer refreshExpired = 720;
    @Autowired
    RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private UserMapper userMapper;


    @Override
    public TokenResponse createToken(AuthDetails details) {
        // 认证token生成
        Map<String, Object> tokenClaims = new HashMap<>();
        Long tokenId = System.currentTimeMillis();
        tokenClaims.put("id",tokenId);
        tokenClaims.put("subject",details.getUser().getId());
        tokenClaims.put("username",details.getUsername());
        tokenClaims.put("nickname",details.getUser().getPassword());
        tokenClaims.put("exp",new Date(System.currentTimeMillis()+1000L * 60 * expired));
        tokenClaims.put("role",details.getAuthorities());
        String token = Jwts.builder().setClaims(tokenClaims).signWith(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)), SignatureAlgorithm.HS256).compact();
        String tokenKey = "token:"+token;
        // 将token放入redis中
        redisTemplate.opsForValue().set(tokenKey,details.getUser().getId());
        redisTemplate.expire(tokenKey,expired, TimeUnit.MINUTES);
        // 添加反向索引
        String userTokenKey = "user_token:"+details.getUser().getId();
        redisTemplate.opsForValue().set(userTokenKey,tokenKey);
        redisTemplate.expire(userTokenKey,expired, TimeUnit.MINUTES);


        // 刷新token生成
        Map<String,Object> refreshClaims = new HashMap<>();
        refreshClaims.put("subject","refresh"+tokenId);
        refreshClaims.put("exp",new Date(System.currentTimeMillis()+ 1000L * 60 * refreshExpired));
        String refreshToken = Jwts.builder().setClaims(refreshClaims).signWith(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)), SignatureAlgorithm.HS256).compact();
        // 将refreshToken放入redis中
        String refreshKey = "refresh:"+refreshToken;
        redisTemplate.opsForValue().set(refreshKey,details.getUser().getId());
        redisTemplate.expire(refreshKey,expired,TimeUnit.MINUTES);
        // 添加反向索引
        String userRefreshKey = "user_refresh:"+details.getUser().getId();
        redisTemplate.opsForValue().set(userRefreshKey,refreshKey);
        redisTemplate.expire(userRefreshKey,refreshExpired,TimeUnit.MINUTES);

        // 返回令牌信息
        return new TokenResponse(token,refreshToken);
    }

    @Override
    public AuthDetails analyzeToken(String token) {
        Claims claim = Jwts.parserBuilder().setSigningKey(secret.getBytes(StandardCharsets.UTF_8)).build().parseClaimsJws(token).getBody();
        TUser user = userMapper.selectById(String.valueOf(claim.get("subject")));
        return new  AuthDetails(user);
    }

    /**
     * 获取用户名
     * @param token 访问令牌
     * @return 用户名
     */
    public String getUserName(String token){
        return this.analyzeToken(token).getUser().getUsername();
    }
}
